/**
 * AnalyzeErrorsBase.java
 * <p/>
 * Copyright (c) Viorel Tacliciu 2009. All Rights Reserved.
 * <p/>
 * This source file may not be copied, modified or redistributed,
 * in whole or in part, in any form or for any reason, without the express
 * written consent of Viorel Tacliciu.
 */
package ro.prjmanager.core.dao;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import ro.prjmanager.core.context.PrjManagerWebContextBuilder;
import ro.prjmanager.core.usr.UserSession;

import javax.persistence.Table;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


@SuppressWarnings("unchecked")
public class GenericDAO<T, ID extends Serializable> extends HibernateDaoSupport {
    private Class<T> persistentClass;
    private String table;

    public UserSession getUserSession(){
        return PrjManagerWebContextBuilder.getBuilder().get().getUserSession();
    }
    public void setPersistentClass(Class<T> persistentClass) {
        this.persistentClass = persistentClass;
        table=persistentClass.getAnnotation(Table.class).name();
    }

    public T find(ID id, boolean lock) {
        T entity;
        if (lock) {
            entity = (T) getSession().get(
                    getPersistentClass(), id, LockMode.UPGRADE);
        } else {
            entity = (T) getSession().get(
                    getPersistentClass(), id);
        }
        return entity;
    }

    public Class<T> getPersistentClass() {
        return persistentClass;
    }


    public List<T> findAll() {
        return find();
    }

    public List<T> listPag(int startPage,int resPerPage){
        SQLQuery sqlQuery=getSession().createSQLQuery("select c from "+table);
        sqlQuery.setMaxResults(resPerPage);
        sqlQuery.setFirstResult(startPage);
        return sqlQuery.list();
    }

    public List<T> listPag(int startPage,int resPerPage,String orderCol,boolean asc,
                           Object... otherItems){
        Criteria criteria=getSession().createCriteria(persistentClass);
        if(otherItems!=null&&otherItems.length>0)
        for(Object crit:otherItems){
           criteria.add(Example.create(crit)); 
        }


        if(asc)
            criteria.addOrder(Order.asc(orderCol));
        else criteria.addOrder(Order.desc(orderCol));
        criteria.setFirstResult(startPage);
        criteria.setMaxResults(resPerPage);
        return criteria.list();
    }




    public List<T> listPagFilter(int startPage,int resPerPage,String sqlFilter){
        Query sqlQuery=getSession().createQuery("select c from "+persistentClass.getName()+" as c "+sqlFilter);
        sqlQuery.setMaxResults(resPerPage);
        sqlQuery.setFirstResult(startPage);
        return sqlQuery.list();

    }

    public List<T> listPag(ro.prjmanager.core.service.SQLQuery sqlQuery){
        List<T> ret=new ArrayList<T>();
        
        sqlQuery.setHibernateSession(getSession());
        sqlQuery.setClazz(persistentClass);

        Query query=sqlQuery.getQuery();
        if(query!=null){
            return query.list();
        }
        return ret;

    }





    public List<T> find(T p_exampleInstance) {
        return find(Example.create(p_exampleInstance));
    }


    public T create(T p_entity) {
        getSession().saveOrUpdate(p_entity);
        return p_entity;
    }

    public T persist(T p_entity) {
        getSession().persist(p_entity);
        return p_entity;
    }

    public void update(T p_entity){
        getSession().update(p_entity);
    }



    public void delete(T entity) {
        getSession().delete(entity);
    }

    public void executeDML(String sql){
        getSession().createSQLQuery(sql).executeUpdate();
    }


    public void delete(ID idEntity){
        delete(find(idEntity,false));
    }


    protected List<T> find(Criterion... p_criterion) {
        Criteria crit = getSession().createCriteria(
                getPersistentClass());
        for (Criterion c : p_criterion) {
            crit.add(c);
        }
        return crit.list();
    }

    public int no(String sqlFilter){
        Query sqlQuery=getSession().createQuery("select count(c.id) from "+persistentClass.getName()+" as c "+sqlFilter);
        return Integer.valueOf(sqlQuery.list().get(0).toString());
    }

    public int no(ro.prjmanager.core.service.SQLQuery sqlQuery){
        Query query=sqlQuery.getQueryNo();        
        return Integer.valueOf(query.uniqueResult().toString());
    }



    public List<T> find(String sql){
        SQLQuery sqlQuery=getSession().createSQLQuery(sql).addEntity(getPersistentClass());
        return sqlQuery.list();
    }

    public List<T> findByHSQL(String hSql){
        Query query=getSession().createQuery(hSql);
        return query.list();
    }

   


}


